package com.chj233.blogOtg.otg;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;


import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;

import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/***
 * 作者：chj233
 * 时间：2022/7/14
 * 描述：
 */
public class OtgHandle implements SerialInputOutputManager.Listener {

    private UsbSerialPort usbSerialPort;
    private SerialInputOutputManager usbIoManager;
    protected SerialInter callback;
    private Future future;

    public boolean open(Context context,int productId, int baudRate) {
        return open(context,productId,baudRate,8,1,0);
    }

    public boolean open(Context context,int productId, int baudRate, int dataBits, int stopBits, int parity) {
        if (usbSerialPort != null) colse();//防止未断开就重连
        UsbSerialDriver drive = getDriver(context,productId);//根据设备产品Id寻找Usb串口对象
        if(drive == null) return false;//未找到串口通信驱动，或者未匹配到产品Id
        UsbDeviceConnection usbConnection = getDeviceConnect(context,drive);
        if(usbConnection == null) return false;//未设置权限被拒绝
        if(drive.getPorts().size() == 0)return false;//没有可用的端口
        for (UsbSerialPort uSerialPort : drive.getPorts()) {
            //若能打开成功 该方法就会返回一个Usb串口对象 反之则返回null
            usbSerialPort = getUsbSerialPort(baudRate,dataBits,stopBits,parity,usbConnection,uSerialPort);
            if (usbSerialPort != null) break; //构建成功
        }
        if (usbSerialPort == null) return false;//循环完毕未构建出Usb串口对象 失败
        //创建一个线程任务 用于循环获取Usb发送来的数据
        usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
        //执行线程
        future = Executors.newSingleThreadExecutor().submit(usbIoManager);
        return true;
    }

    public void onDataListener(SerialInter callback) {
        this.callback = callback;
    }

    public void sendData(String data) {
        try {
            byte[] datas = data.getBytes();
            usbSerialPort.write(datas,100);
        } catch (Exception e) {
            onRunError(e);
        }
    }

    public void colse() {
        if (future != null) future.cancel(true);
        if(usbIoManager != null) usbIoManager.stop();
        try {
            if (usbSerialPort != null) usbSerialPort.close();
        } catch (Exception e) {
            onRunError(e);
        }
        future = null;
        usbIoManager = null;
        usbSerialPort = null;
    }

    //通过设备的产品Id获取设备的驱动
    protected UsbSerialDriver getDriver(Context context,int productId){
        UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        for(UsbDevice device : usbManager.getDeviceList().values()) {
            if (device == null || device.getProductId() != productId) continue;//检查设备产品Id
            UsbSerialDriver drive = UsbSerialProber.getDefaultProber().probeDevice(device);//验证驱动
            if (drive == null) drive = CustomProber.getCustomProber().probeDevice(device);//若没有 再次验证驱动
            if (drive == null) continue; //没有驱动
            return drive;//直接返回驱动
        }
        return null;
    }

    //获取Usb连接对象
    protected UsbDeviceConnection getDeviceConnect(Context context,UsbSerialDriver drive){
        UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        if (!usbManager.hasPermission(drive.getDevice())) return null;//没有权限
        return usbManager.openDevice(drive.getDevice());
    }

    //构建Usb串口对象
    private UsbSerialPort getUsbSerialPort(int baudRate, int dataBits, int stopBits, int parity, UsbDeviceConnection usbConnection, UsbSerialPort uSerialPort) {
        try{
            uSerialPort.open(usbConnection);
            uSerialPort.setParameters(baudRate, dataBits, stopBits, parity);
            return uSerialPort;
        }catch (Exception e){
            try{
                uSerialPort.close();
            }catch (Exception cle){
                e.printStackTrace();
            }finally {
                return null;
            }
        }
    }

    /**
     * =============================================================================================
     *
     * =============================================================================================
     */
    @Override
    public void onNewData(byte[] b) {
        try{
            if (callback != null) callback.readData(b);
        }catch (Exception e){
            onRunError(e);
        }
    }

    @Override
    public void onRunError(Exception e) {
        if (callback != null) callback.connectMsg(e);
    }

}
